﻿using System;
using System.ComponentModel;
using System.Windows.Forms;

using BizElements.Core;

namespace BizElements.Generator
{
    public partial class SqlServerConnCtl : UserControl, IMetaDataSourceUi
    {
        public SqlServerConnCtl()
        {
            InitializeComponent();
        }

        #region Parse and test metadata source.

        private void uiConnect_Click(object sender, EventArgs e)
        {
            CreateAndTestNewMetaDataSource();
        }

        private void CreateAndTestNewMetaDataSource()
        {
            DisposeCurrentMetaDataSource();
            var connStr = ParseConnectionString();
            if (connStr == null)
                return;

            this.MetaDataSource = DbGeneratorComponentFactory.GetMetadataSource(this.dbms, connStr.Build());
            bool isTestOk = TestConnection();
            if (isTestOk)
            {
                FireConnected();
                this.uiConnect.Enabled = false;
                this.uiDisconnect.Enabled = true;
            }
            else
            {
                this.MetaDataSource = null;
            }
        }

        private MsSqlConnStringBuilder ParseConnectionString()
        {
            MsSqlConnStringBuilder builder = new MsSqlConnStringBuilder()
            {
                Server = this.uiServer.Text.Trim(),
                Catalog = this.uiCatalog.Text.Trim(),
                UseWindowsAuthentication = this.uiWinAuthentication.Checked,
                LoginId = this.uiLogin.Text.Trim(),
                Password = this.uiPassword.Text.Trim()
            };

            string[] errors = builder.Validate();
            if (errors.Length > 0)
            {
                builder = null;
                string errmsg = string.Join(Environment.NewLine, errors);
                MessageBox.Show(errmsg);
            }

            return builder;
        }

        private bool TestConnection()
        {
            try
            {
                this.Cursor = Cursors.AppStarting;
                this.MetaDataSource.OpenConnection();
                this.MetaDataSource.CloseConnection();
                return true;
            }
            catch (Exception ex)
            {
                string errmsg = Messages.SqlServerConnCtl_CannotConnectToDatabase + Environment.NewLine + ex.ToString();
                MessageBox.Show(errmsg, Messages.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void FireConnected()
        {
            if (this.Connected != null)
                Connected(this, new MetaDataSourceEventArgs(this.MetaDataSource));
        }

        #endregion

        #region Disconnect and dispose metadata source.

        private void uiDisconnect_Click(object sender, EventArgs e)
        {
            DisconnectAndDisposeCurrentMetaDataSource();
        }

        private void DisconnectAndDisposeCurrentMetaDataSource()
        {
            DisposeCurrentMetaDataSource();
            this.uiConnect.Enabled = true;
            this.uiDisconnect.Enabled = false;
            FireDisconnected();
        }

        private void FireDisconnected()
        {
            if (this.Disconnected != null)
                Disconnected(this, null);
        }

        private void DisposeCurrentMetaDataSource()
        {
            if (this.MetaDataSource != null)
            {
                this.MetaDataSource.CloseConnection();
                this.MetaDataSource = null;
            }
        }

        #endregion

        #region Authentication mode.

        private void uiWinAuthentication_CheckedChanged(object sender, EventArgs e)
        {
            SeAuthenticationModeControls();
        }

        private void uiSqlServerAuthentication_CheckedChanged(object sender, EventArgs e)
        {
            SeAuthenticationModeControls();
        }

        private void SeAuthenticationModeControls()
        {
            if (this.uiWinAuthentication.Checked)
            {
                this.uiLogin.Enabled = false;
                this.uiPassword.Enabled = false;
            }
            else
            {
                this.uiLogin.Enabled = true;
                this.uiPassword.Enabled = true;
            }
        }

        #endregion

        #region IMetaDataSourceUi Members.

        [Browsable(false)]
        public UserControl Control
        {
            get { return this; }
        }

        [Browsable(false)]
        public IMetadataSource MetaDataSource { get; private set; }

        DbmsType dbms = DbmsType.SqlServer_2005;

        public DbmsType Dbms
        {
            get { return this.dbms; }
            set
            {
                if (DbGeneratorComponentFactory.IsSqlServer(value))
                    this.dbms = value;
                else
                    throw new ArgumentException(Messages.SqlServerConnCtl_OnlyMsSqlServerDBMSsAreSupported);
            }            
        }

        public event EventHandler<MetaDataSourceEventArgs> Connected;

        public event EventHandler<MetaDataSourceEventArgs> Disconnected;

        #endregion

        #region Settings.

        public void ReadSettings(BizElementsSettings settings)
        {
            DisconnectAndDisposeCurrentMetaDataSource();
            this.uiServer.Text = settings["SqlServerConn_Server"];
            this.uiCatalog.Text = settings["SqlServerConn_Catalog"];
            this.uiWinAuthentication.Checked = (settings["SqlServerConn_WinAuthentication"] == "true");
            this.uiLogin.Text = settings["SqlServerConn_Login"];
            this.uiPassword.Text = settings["SqlServerConn_Password"];
        }

        public void WriteSettings(BizElementsSettings settings)
        {
            settings["SqlServerConn_Server"] = this.uiServer.Text.Trim();
            settings["SqlServerConn_Catalog"] = this.uiCatalog.Text.Trim();
            settings["SqlServerConn_WinAuthentication"] = (this.uiWinAuthentication.Checked) ? "true" : "false";
            settings["SqlServerConn_Login"] = this.uiLogin.Text.Trim();
            settings["SqlServerConn_Password"] = this.uiPassword.Text.Trim();
        }

        #endregion

        sealed class MsSqlConnStringBuilder
        {
            #region Properties.

            public string Server { get; set; }
            public string Catalog { get; set; }
            public bool UseWindowsAuthentication { get; set; }
            public string LoginId { get; set; }
            public string Password { get; set; }

            #endregion

            #region Methods.

            public string[] Validate()
            {                
                if (string.IsNullOrEmpty(this.Server) || string.IsNullOrEmpty(this.Catalog))
                    return new string[] { Messages.SqlServerConnCtl_ServerAndCatalogNamesAreRequired };

                if (!this.UseWindowsAuthentication)
                {                    
                    if (string.IsNullOrEmpty(this.LoginId) || string.IsNullOrEmpty(Password))
                        return new string[] { Messages.SqlServerConnCtl_LoginIdAndPwdAreRequiredIfSqlAuthIsSelected };
                }

                return new string[0];
            }

            public string Build()
            {
                string connectionString = "";
                connectionString += "data source=" + this.Server + ";";
                connectionString += "initial catalog=" + this.Catalog + ";";
                if (this.UseWindowsAuthentication)
                {
                    connectionString += "integrated security=SSPI;persist security info=False;packet size=4096";
                }
                else
                {
                    connectionString += "UID=" + this.LoginId + ";";
                    connectionString += "PWD=" + this.Password;
                }

                return connectionString;
            }

            #endregion
        }
    }
}
